﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Skybot.Base.Mulitply;
using Skybot.BaseSocket;
using InCom.Utilities;
using System.Net.Sockets;
using InCom.Utilities.Extension;
using Skybot.Base.Connect;
using Skybot.Base.Mulitply;
using Skybot.BaseSocket;
using Skybot.Base;
using Skybot.Extension;

namespace Skybot.Base.Connect
{
    /// <summary>
    /// --- TCP服务器 主接入类
    /// </summary>
    public class OTATcpServerHelper
    {
        /// <summary>
        /// 解析线程对像,用于处理所有协议的拆包解析类队列
        /// </summary>
        internal TaskReceiverProtocolResolve taskReceiver = new TaskReceiverProtocolResolve();

        /// <summary>
        /// 并行处理功能
        /// </summary>
        private MultiplyOperationHelper multiylyHelper = new MultiplyOperationHelper(BaseConfig.ThreadNum);

        /// <summary>
        /// --- TCP服务器 主接入类
        /// </summary>
        public OTATcpServerHelper()
        {
            asyncServer.OnAccepted += asyncServer_OnAccepted;
            asyncServer.OnClientClosed += asyncServer_OnClientClosed;
            //接收数据
            asyncServer.Handler = ServerReceiveHandler;

            //始解析服务
            taskReceiver.Start();
            //开始并行处理
            multiylyHelper.Start();
            //开始解析协议
            multiylyHelper.OperationHandler = OperationHandler;
 
        }

        private  TCPAsyncServer asyncServer = new TCPAsyncServer();

        /// <summary>
        /// 开始服务
        /// </summary>
        public void Start(int port)
        {
            asyncServer.Listen(port);
            IsRunning = true;
            LogProvider.Create().Write(EventType.Information, string.Format(" ---协议OTA 地址开始进行启动"));
        }

        #region TCP接收器池
        /// <summary>
        /// TCP接收器池
        /// </summary>
        private Skybot.Base.Pool.BasePool<TCPReceiver> tcpReceivePool = new Skybot.Base.Pool.BasePool<TCPReceiver>(100, 10000, false);


        /// <summary>
        /// 创建一个接收TCPReceiver对象,设置最大接收字节数
        /// </summary>
        /// <returns></returns>
        private TCPReceiver CreateReceiveTCPReceiver()
        {
            TCPReceiver e = new TCPReceiver();

            return e;
        }


        /// <summary>
        /// 租赁一个接收TCPReceiver对象
        /// </summary>
        /// <returns></returns>
        private TCPReceiver RentReveiveTCPReceiver()
        {
            TCPReceiver e = tcpReceivePool.Pop();

            return e != null ? e : CreateReceiveTCPReceiver();
        }

        /// <summary>
        /// 归还一个接收TCPReceiver参数
        /// </summary>
        /// <param name="e">还池</param>
        private void GivebackReceiveTCPReceiver(TCPReceiver e)
        {
            if (e == null)
            {
                return;
            }
            try
            {
                e.TargetSocket = null;
                e.StopParseProtocol();
            }
            catch (Exception ex)
            {
                LogProvider.Create().Write(EventType.Information, string.Format("TCPReceiver还池时出现问题:{0}", ex));
            }
            tcpReceivePool.Push(e);
        }

        #endregion

        #region 连接状态与接收数据
        /// <summary>
        ///同步节点接收器 Key 是 IPEndPoint.ToString()
        /// </summary>
        private System.Collections.Concurrent.ConcurrentDictionary<string, TCPReceiver> _SyncPointReceives = new ConcurrentDictionary<string, TCPReceiver>();

        /// <summary>
        /// 接收数据包
        /// </summary>
        /// <param name="e">节点</param>
        /// <param name="ep"></param>
        protected void ServerReceiveHandler(SocketAsyncEventArgs e, EndPoint ep)
        {
            var cursocket = e.UserToken as Socket;
            if (cursocket == null) return;
            //接收数据成功
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                var ipep = (IPEndPoint)ep;
                var epstr = ipep.ToString();
                TCPReceiver receiver = AddReceiver(epstr, cursocket);
                if (receiver != null)
                {
                    var receivebytes = new byte[e.BytesTransferred];
                    //进行数组复制
                    Buffer.BlockCopy(e.Buffer, 0, receivebytes, 0, receivebytes.Length);
                    receiver.Receive(receivebytes);
                    //开始解析队列,加入集中处理
                    taskReceiver.Push(receiver);
                }
            }
        }

        /// <summary>
        /// 连接关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void asyncServer_OnClientClosed(object sender, TCPAsyncServerCloseConnEventArgs e)
        {
            if (e.ClosedEndPoint == null)
            {
                return;
            }
            string epStr = e.ClosedEndPoint.ToString();
            try
            {
                //断开客户端节点
                asyncServer.CloseClient((IPEndPoint)e.ClosedEndPoint);
                //移除节点信息
                var rec = RemoveReceiver(epStr);
                GivebackReceiveTCPReceiver(rec);
                //当前对像不进行打印处理,因为可能打印两次
                if (!(sender is  OTATcpServerHelper))
                {                   
                    #region 调试模式
                    //调试模式
                    if (BaseConfig.IsDebug)
                    {
                    LogProvider.Create().Write(EventType.Information, string.Format("---断开TCP连接:{0},共:{1}个客户端在线", epStr, asyncServer.CurrentConnectionCount));
                    }
                    #endregion
                }
            }
            catch (ObjectDisposedException)
            {
            }
            catch (SocketException)
            {
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 新客户端接入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void asyncServer_OnAccepted(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
        {
            if (e.AcceptSocket != null)
            {
                try
                {
                    string epstr = e.AcceptSocket.RemoteEndPoint.ToString();
                    AddReceiver(epstr, e.AcceptSocket);

                    #region 调试模式
                    //调试模式
                    if (BaseConfig.IsDebug)
                    {
                        LogProvider.Create().Write(EventType.Information, string.Format("接收到---,TCP客户端:{0}连接:共{1}客户端在线", epstr, asyncServer.CurrentConnectionCount));
                    }
                    #endregion
                }
                catch (Exception ex)
                {
                    LogProvider.Create().Write(EventType.Information, string.Format("接收到TCP客户端Accept出错了"));
                }
            }
        }

        /// <summary>
        /// 添加一个接收器到消息节点中
        /// </summary>
        /// <param name="epstr">远程节点</param>
        /// <param name="socket">当前socket对像</param>
        /// <returns></returns>
        protected TCPReceiver AddReceiver(string epstr, Socket socket)
        {
            TCPReceiver receiver;
            //是否包含指定的Key
            if (!SyncPointReceives.ContainsKey(epstr))
            {
                //从池中获取一个receiver对像
                receiver = RentReveiveTCPReceiver();
                //设置各属性
                receiver.PackageFoot = new byte[] { 0x23 };
                receiver.PackageHead = new byte[] { 0x23 };
                receiver.ProtocolReceivedHandler = ProtocolProcess;
                receiver.ParsePackegHandler = ParsePackeg;
                receiver.TargetSocket = socket;
                //添加到集合中
                SyncPointReceives.TryAdd(epstr, receiver);
            }
            else
            {
                SyncPointReceives.TryGetValue(epstr, out receiver);
            }
            return receiver;
        }

        /// <summary>
        /// 移除节点信息,如果没有找到指定节点的接收器,则返回null
        /// </summary>
        /// <param name="epstr">消息节点</param>
        /// <returns></returns>
        protected TCPReceiver RemoveReceiver(string epstr)
        {
            TCPReceiver receiver;
            SyncPointReceives.TryRemove(epstr, out receiver);
            return receiver;
        }

        #endregion

        #region 协议解析相关
        /// <summary>
        /// 解析一个完整的包
        /// 1.0x23转议
        /// 2.数据校验
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="socket"></param>
        /// <returns></returns>
        protected IBaseProtocol ParsePackeg(byte[] bytes, Socket socket)
        {
            IBaseProtocol protocol = null;
            if (socket != null)
            {
                if (socket.RemoteEndPoint != null)
                {
                    #region 性能记数
                    //增加接收包部数
                    //System.Threading.Interlocked.Increment(ref OtaProcessStateAdapter.Instance.recordReceiveCount);
                    #endregion
                    string epstr = socket.RemoteEndPoint.ToString();
                    //采用多线程并行处理,提升性能
                    multiylyHelper.Push(epstr, socket, socket.RemoteEndPoint, bytes, ProtocolType.Tcp);
                }
            }
            return protocol;
        }
 
        /// <summary>
        /// 协议解析,校验,多线程处理节点,
        /// </summary>
        /// <param name="bytes">末转议协议数据</param>
        /// <param name="handler"></param>
        /// <param name="endPoint"></param>
        public bool OperationHandler(byte[] bytes, System.Net.Sockets.Socket handler, System.Net.EndPoint endPoint)
        { 
         var message=bytes;//或者散板
            //检验.............
            if (message.Check())
            {
                if (BaseConfig.IsRecorded)
                {
                    
                    /////////写入日志
                    TerminalMessageRecordOtmOTA.Create().Push(message);
                }
                LogProvider.Create().Write(EventType.Error, string.Format("---未验证通过数据:{0}", message.ToHex()));
                ////////////////////////////////////////////////////////////////////////////////////////日志记录////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                return false;
            }
            try
            {
                //解析协议
 
                    //转入逻辑处理队列
               
                    ////////////////////////////////////////////////////////////////////////////////////////日志记录////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                     if (BaseConfig.IsRecorded)
                {
                    
                    /////////写入日志
                    TerminalMessageRecordOtmOTA.Create().Push(message);
                }
                    return true;
         
                 
            }
            catch (Exception ex)
            {
                LogProvider.Create().Write(EventType.Error, string.Format("---解析时出现问题,数据:{0},错误信息:{1}", message.ToHex(), ex));
            }
            ////////////////////////////////////////////////////////////////////////////////////////日志记录////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  if (BaseConfig.IsRecorded)
                {
                    
                    /////////写入日志
                    TerminalMessageRecordOtmOTA.Create().Push(message);
                }
            return false;
        }

        /// <summary>
        /// 协议解析处理方法 
        /// </summary>
        /// <param name="protcol">协议实体</param>
        /// <param name="socket">Socket数据包</param>
        protected void ProtocolProcess(IBaseProtocol protcol, Socket socket)
        {

        }
        #endregion

        /// <summary>
        /// 关闭服务
        /// </summary>
        public void Stop()
        {
            if (asyncServer != null)
            {
                asyncServer.Stop();
                IsRunning = false;
            }
        }

        public bool IsRunning { get; set; }

        /// <summary>
        ///同步节点接收器 Key 是 IPEndPoint.ToString()
        /// </summary>
        public ConcurrentDictionary<string, TCPReceiver> SyncPointReceives
        {
            get { return _SyncPointReceives; }
        }
    }
}
